﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using AFI.Speargun.Web.Models.Validation;
using System.Collections.Specialized;
using System.Reflection;
using System.Text;
using System.IO;
using System.Xml.Serialization;
using System.Transactions;
using AFI.Speargun.Web.Core;

namespace AFI.Speargun.Web.Models
{
    public class SpeargunService : ISpeargunService
    {
        private IValidationDictionary _validationDictionary;
        private ISpeargunRepository _repository;

        public SpeargunService(IValidationDictionary validationDictionary)
            : this(validationDictionary, new EntitySpeargunRepository())
        { }

        public SpeargunService(IValidationDictionary validationDictionary, ISpeargunRepository repository)
        {
            _validationDictionary = validationDictionary;
            _repository = repository;
        }

        #region Category methods

        public bool ValidateCategory(Category category)
        {

            return _validationDictionary.IsValid;
        }

        public bool ValidateDeleteCategory(Guid categoryId)
        {
            if (categoryId == Guid.Empty)
                _validationDictionary.AddError("Category", "The ROOT cannot delete.");

            return _validationDictionary.IsValid;
        }

        public bool CreateCategory(Guid parentCategoryId, Category category)
        {
            // Validation logic
            if (!ValidateCategory(category))
                return false;

            // Database logic
            try
            {
                category.CategoryId = Guid.NewGuid();
                category.AssetEntryAdditionalDefinition = String.Empty;
                category.Parent = this.GetCategory(parentCategoryId);

                _repository.CreateCategory(category);
            }
            catch (Exception ex)
            {
                _validationDictionary.AddError("Exception", ex.ToString());
                return false;
            }
            return true;
        }

        public bool DeleteCategory(Guid categoryId)
        {
            // Validation logic
            if (!ValidateDeleteCategory(categoryId))
                return false;

            try
            {
                _repository.DeleteCategory(this.GetCategory(categoryId));
            }
            catch (Exception ex)
            {
                _validationDictionary.AddError("Exception", ex.ToString());
                return false;
            }
            return true;
        }

        public bool EditCategory(Category category)
        {
            // Validation logic
            if (!ValidateCategory(category))
                return false;

            // Database logic
            try
            {
                _repository.EditCategory(category);
            }
            catch (Exception ex)
            {
                _validationDictionary.AddError("Exception", ex.ToString());
                return false;
            }
            return true;
        }

        public Category GetCategory(Guid? categoryId)
        {
            if (categoryId.HasValue)
                return _repository.GetCategory(categoryId.Value);

            return _repository.GetCategory(Guid.Empty);
        }
        #endregion

        #region Department methods

        public bool ValidateDepartment(Department department)
        {

            return _validationDictionary.IsValid;
        }

        public bool ValidateDeleteDepartment(Guid departmentId)
        {
            if (departmentId == Guid.Empty)
                _validationDictionary.AddError("Department", "The ROOT cannot delete.");

            return _validationDictionary.IsValid;
        }

        public bool CreateDepartment(Guid parentDepartmentId, Department department)
        {
            // Validation logic
            if (!ValidateDepartment(department))
                return false;

            // Database logic
            try
            {
                department.DepartmentId = Guid.NewGuid();
                department.Parent = this.GetDepartment(parentDepartmentId);

                _repository.CreateDepartment(department);
            }
            catch (Exception ex)
            {
                _validationDictionary.AddError("Exception", ex.ToString());
                return false;
            }
            return true;
        }

        public bool DeleteDepartment(Guid departmentId)
        {
            // Validation logic
            if (!ValidateDeleteDepartment(departmentId))
                return false;

            try
            {
                _repository.DeleteDepartment(this.GetDepartment(departmentId));
            }
            catch (Exception ex)
            {
                _validationDictionary.AddError("Exception", ex.ToString());
                return false;
            }
            return true;
        }

        public bool EditDepartment(Department department)
        {
            // Validation logic
            if (!ValidateDepartment(department))
                return false;

            // Database logic
            try
            {
                _repository.EditDepartment(department);
            }
            catch (Exception ex)
            {
                _validationDictionary.AddError("Exception", ex.ToString());
                return false;
            }
            return true;

        }

        public Department GetDepartment(Guid? departmentId)
        {
            if (departmentId.HasValue)
                return _repository.GetDepartment(departmentId.Value);

            return _repository.GetDepartment(Guid.Empty);
        }

        #endregion

        #region AssetEntry methods

        public bool ValidateAssetEntry(AssetEntry assetEntry)
        {

            return _validationDictionary.IsValid;
        }

        public bool ValidateDeleteAssetEntry(Guid assetEntryId)
        {
            return _validationDictionary.IsValid;
        }

        public bool CreateAssetEntry(Guid categoryId, Guid departmentId, Guid depreciationCurrencyId, Guid acquisitionModeId, AssetEntry assetEntry)
        {
            // Validation logic
            if (!ValidateAssetEntry(assetEntry))
                return false;

            // Database logic
            try
            {
                assetEntry.AssetEntryId = Guid.NewGuid();

                assetEntry.Category = this.GetCategory(categoryId);
                assetEntry.Department = this.GetDepartment(departmentId);
                assetEntry.Currency = this.GetCurrency(depreciationCurrencyId);
                assetEntry.AcquisitionMode = this.GetAcquisitionMode(acquisitionModeId);

                assetEntry.EntryCreateDate = DateTime.Now;

                _repository.CreateAssetEntry(assetEntry);

            }
            catch (Exception ex)
            {
                _validationDictionary.AddError("Exception", ex.ToString());
                return false;
            }
            return true;
        }

        public bool DeleteAssetEntry(Guid assetEntryId)
        {
            // Validation logic
            if (!ValidateDeleteAssetEntry(assetEntryId))
                return false;

            try
            {
                _repository.DeleteAssetEntry(this.GetAssetEntry(assetEntryId));
            }
            catch (Exception ex)
            {
                _validationDictionary.AddError("Exception", ex.ToString());
                return false;
            }
            return true;
        }

        public bool EditAssetEntry(AssetEntry assetEntry)
        {
            // Validation logic
            if (!ValidateAssetEntry(assetEntry))
                return false;

            // Database logic
            try
            {
                _repository.EditAssetEntry(assetEntry);
            }
            catch (Exception ex)
            {
                _validationDictionary.AddError("Exception", ex.ToString());
                return false;
            }
            return true;

        }

        public AssetEntry GetAssetEntry(Guid assetEntryId)
        {
            return _repository.GetAssetEntry(assetEntryId);
        }

        #endregion

        #region AssetEntryAdditional methods

        public bool ValidateAssetEntryAdditional(AssetEntryAdditional assetEntryAdditional)
        {

            return _validationDictionary.IsValid;
        }

        public bool EditAssetEntryAdditional(AssetEntryAdditional assetEntryAdditional)
        {
            // Validation logic
            if (!ValidateAssetEntryAdditional(assetEntryAdditional))
                return false;

            // Database logic
            try
            {
                try
                {
                    _repository.EditAssetEntryAdditional(assetEntryAdditional);
                }
                catch (InvalidOperationException ex)
                {
                    assetEntryAdditional.AssetEntry = _repository.GetAssetEntry(assetEntryAdditional.AssetEntryId);
                    _repository.CreateAssetEntryAdditional(assetEntryAdditional);
                }
            }
            catch (Exception ex)
            {
                _validationDictionary.AddError("Exception", ex.ToString());
                return false;
            }

            return true;
        }

        public Dictionary<AssetEntryAdditionalDefinitionField, string> GetAssetEntryAdditional(Guid assetEntryId)
        {
            AssetEntry assetEntry = _repository.GetAssetEntry(assetEntryId);

            if (!assetEntry.AssetEntryAdditionalReference.IsLoaded)
                assetEntry.AssetEntryAdditionalReference.Load();

            if (assetEntry.AssetEntryAdditional == null)
                assetEntry.AssetEntryAdditional = new AssetEntryAdditional();

            if (!assetEntry.CategoryReference.IsLoaded)
                assetEntry.CategoryReference.Load();

            Type t = typeof(AssetEntryAdditional);

            var q = from p in assetEntry.Category.AssetEntryAdditionalDefinitionSchema
                    where p.Enable
                    orderby p.Order
                    select p;

            Dictionary<AssetEntryAdditionalDefinitionField, string> assetEntryAdditionalDict = new Dictionary<AssetEntryAdditionalDefinitionField, string>();

            foreach (var i in q)
            {
                string value = "[null]";
                object valueObj = t.GetProperty(i.FieldName).GetValue(assetEntry.AssetEntryAdditional, null);
                if (valueObj != null)
                    value = valueObj.ToString();

                assetEntryAdditionalDict.Add(i, value);
            }

            return assetEntryAdditionalDict;
        }

        #endregion
        
        #region Currency methods

        public bool ValidateCurrency(Currency currency)
        {

            return _validationDictionary.IsValid;
        }

        public bool CreateCurrency(Currency currency)
        {
            // Validation logic
            if (!ValidateCurrency(currency))
                return false;

            // Database logic
            try
            {
                currency.CurrencyId = Guid.NewGuid();

                _repository.CreateCurrency(currency);
            }
            catch (Exception ex)
            {
                _validationDictionary.AddError("Exception", ex.ToString());
                return false;
            }
            return true;
        }

        public bool DeleteCurrency(Guid currencyId)
        {
            try
            {
                _repository.DeleteCurrency(this.GetCurrency(currencyId));
            }
            catch (Exception ex)
            {
                _validationDictionary.AddError("Exception", ex.ToString());
                return false;
            }
            return true;
        }

        public bool EditCurrency(Currency currency)
        {
            // Validation logic
            if (!ValidateCurrency(currency))
                return false;

            // Database logic
            try
            {
                _repository.EditCurrency(currency);
            }
            catch (Exception ex)
            {
                _validationDictionary.AddError("Exception", ex.ToString());
                return false;
            }
            return true;
        }

        public Currency GetCurrency(Guid currencyId)
        {
            return _repository.GetCurrency(currencyId);
        }

        public IEnumerable<Currency> ListCurrencies()
        {
            return _repository.ListCurrencies();
        }

        #endregion

        #region AcquisitionMode methods

        public bool ValidateAcquisitionMode(AcquisitionMode acquisitionMode)
        {

            return _validationDictionary.IsValid;
        }

        public bool CreateAcquisitionMode(AcquisitionMode acquisitionMode)
        {
            // Validation logic
            if (!ValidateAcquisitionMode(acquisitionMode))
                return false;

            // Database logic
            try
            {
                acquisitionMode.AcquisitionModeId = Guid.NewGuid();

                _repository.CreateAcquisitionMode(acquisitionMode);
            }
            catch (Exception ex)
            {
                _validationDictionary.AddError("Exception", ex.ToString());
                return false;
            }
            return true;
        }

        public bool DeleteAcquisitionMode(Guid acquisitionModeId)
        {
            try
            {
                _repository.DeleteAcquisitionMode(this.GetAcquisitionMode(acquisitionModeId));
            }
            catch (Exception ex)
            {
                _validationDictionary.AddError("Exception", ex.ToString());
                return false;
            }
            return true;
        }

        public bool EditAcquisitionMode(AcquisitionMode acquisitionMode)
        {
            // Validation logic
            if (!ValidateAcquisitionMode(acquisitionMode))
                return false;

            // Database logic
            try
            {
                _repository.EditAcquisitionMode(acquisitionMode);
            }
            catch (Exception ex)
            {
                _validationDictionary.AddError("Exception", ex.ToString());
                return false;
            }
            return true;
        }

        public AcquisitionMode GetAcquisitionMode(Guid acquisitionModeId)
        {
            return _repository.GetAcquisitionMode(acquisitionModeId);
        }

        public IEnumerable<AcquisitionMode> ListAcquisitionModes()
        {
            return _repository.ListAcquisitionModes();
        }

        #endregion

        #region InventoryChecking methods

        public bool ValidateInventoryChecking(InventoryChecking inventoryChecking)
        {

            return _validationDictionary.IsValid;
        }

        public bool CreateInventoryChecking(Guid departmentId, InventoryChecking inventoryChecking)
        {
            // Validation logic
            if (!ValidateInventoryChecking(inventoryChecking))
                return false;

            // Database logic
            try
            {
                inventoryChecking.InventoryCheckingId = Guid.NewGuid();
                inventoryChecking.Department = _repository.GetDepartment(departmentId);
                inventoryChecking.CreateDate = DateTime.Now;
                inventoryChecking.Status = (int)InventoryCheckingStatus.NotStarted;

                _repository.CreateInventoryChecking(inventoryChecking);
            }
            catch (Exception ex)
            {
                _validationDictionary.AddError("Exception", ex.ToString());
                return false;
            }
            return true;

        }

        public bool DeleteInventoryChecking(Guid inventoryCheckingId)
        {
            throw new NotImplementedException();
        }

        public bool EditInventoryChecking(InventoryChecking inventoryChecking)
        {
            // Validation logic
            if (!ValidateInventoryChecking(inventoryChecking))
                return false;

            // Database logic
            try
            {
                _repository.EditInventoryChecking(inventoryChecking);
            }
            catch (Exception ex)
            {
                _validationDictionary.AddError("Exception", ex.ToString());
                return false;
            }
            return true;
        }

        public InventoryChecking GetInventoryChecking(Guid inventoryCheckingId)
        {
            return _repository.GetInventoryChecking(inventoryCheckingId);
        }

        public IEnumerable<InventoryChecking> ListInventoryCheckings()
        {
            return _repository.ListInventoryCheckings();
        }

        #endregion

        #region AssetInventory methods

        public bool ValidateAssetInventory(AssetInventory assetInventory)
        {

            return _validationDictionary.IsValid;
        }

        public bool CreateAssetInventory(Guid assetEntryId, AssetInventory assetInventory)
        {
            // Validation logic
            if (!ValidateAssetInventory(assetInventory))
                return false;

            // Database logic
            try
            {
                assetInventory.AssetInventoryId = Guid.NewGuid();
                assetInventory.AssetEntry = this.GetAssetEntry(assetEntryId);

                _repository.CreateAssetInventory(assetInventory);
            }
            catch (Exception ex)
            {
                _validationDictionary.AddError("Exception", ex.ToString());
                return false;
            }
            return true;
        }

        public bool DeleteAssetInventory(Guid inventoryCheckingId)
        {
            throw new NotImplementedException();
        }

        public bool EditAssetInventory(AssetInventory assetInventory)
        {
            // Validation logic
            if (!ValidateAssetInventory(assetInventory))
                return false;

            // Database logic
            try
            {
                _repository.EditAssetInventory(assetInventory);
            }
            catch (Exception ex)
            {
                _validationDictionary.AddError("Exception", ex.ToString());
                return false;
            }
            return true;
        }

        public AssetInventory GetAssetInventory(Guid assetInventoryId)
        {
            return _repository.GetAssetInventory(assetInventoryId);
        }

        public IEnumerable<AssetInventory> ListAssetInventories(Guid assetEntryId)
        {
            return _repository.ListAssetInventories(assetEntryId);
        }

        #endregion
    }
}
